/*
    Copyright (c) 2001-2002 BSQUARE Corporation.  All rights reserved.
    
    Memory access commands
    
    
*/

#include "includes.h"
#include "sdconfig.h"

#define MEMWR_DEGBUG


const char writeHelp[] = 
    "Syntax write [-8|16|32] <addr> <Val> [count]\r\n\
   \tWrite  <Val> at address <addr>\r\n\
   \t-8|16|32 specifies access width. 32 is default\r\n\
   \tcount repeats the write to the consecutive [count] locations \r\n";

const char readHelp[] = 
    "Syntax read [-8|16|32] <addr> [count]\r\n\
   \tRead  <Val> from address <addr>\r\n\
   \t-8|16|32 specifies access width. 32 is default\r\n\
   \tcount repeats the read from the consecutive [count] locations \r\n";

const char memtest[] = 
    "Syntax memtest <addr1> <addr2> \r\n\
   \rExamples: memtest 50000000 5FF00000 \r\n\
   \taddr1: Test start address \r\n\
   \taddr2: Test end address \r\n";


int
MemReadValue(int argc, char *argv[])
{
    int ErrorCode = ERROR_SUCCESS;
    ULONG Addr;
    ULONG Value;
    int Size;
    int Width=4;
    int i=1;
    
        
    if (argc < 2) {
        ErrorCode = ERROR_MISSINGARGS;        
        goto ErrorReturn;        
    }


    while ((i < argc) && argv[i][0] == '-') {
        // is a switch, parse it.
        if (argv[i][1] == '8') {
            // bytes
            Width = 1;
        }
        if (argv[i][1] == '1') {
            // words
            Width = 2;
        }
        i++;        
    }

    if (!strtohex(argv[i], (unsigned int *)&Addr)) {
        ErrorCode = ERROR_BADARG;
        goto ErrorReturn;
    }
    
    if (((4==Width) && (Addr & 3)) ||
        ((2==Width) && (Addr & 1))) {
        CLIOutputString(" Unaligned Address\r\n");
        ErrorCode = ERROR_UNALIGNEDACCESS;
        goto ErrorReturn;
    }


    if ((i + 1) < argc) {
        if (!strtohex(argv[i+1], (unsigned int *)&Size)) {
            ErrorCode = ERROR_BADARG;
            goto ErrorReturn;
        }
    } else {
        Size = 1;
    }

    CLIOutputString("\r\n");        
    
    for (i=0;i<Size;i += Width) {
        switch (Width) {
        case 4:
            Value = (*PULONG(Addr + i));
            CLIOutputString("%X:%X",(Addr+i), Value);
			break;
        case 2:
            Value = (*PUSHORT(Addr + i));
            CLIOutputString("%X:%X",(Addr+i), Value);
			break;
        case 1:
            Value = (*PUCHAR(Addr + i));
            CLIOutputString("%X:%X",(Addr+i), Value);
			break;
        }
        CLIOutputString("\r\n");        
    }
    
    CLIOutputString("\r\nOk");
    
    
ErrorReturn:
    return ErrorCode;	
}

int
MemWriteValue(int argc, char *argv[])
{
    int ErrorCode = ERROR_SUCCESS;
    ULONG Addr;
    ULONG Value;
    int Iterations;
    int Width=4;
    int i=1;
    
    if (argc < 2) {
        ErrorCode = ERROR_MISSINGARGS;        
        goto ErrorReturn;        
    }


    while ((i < argc) && argv[i][0] == '-') {
        // is a switch, parse it.
        if (argv[i][1] == '8') {
            // bytes
            Width = 1;
        }
        if (argv[i][1] == '1') {
            // words
            Width = 2;
        }
        i++;        
    }

    if (!strtohex(argv[i], (unsigned int *)&Addr)) {
        ErrorCode = ERROR_BADARG;
        goto ErrorReturn;
    }
    
    if (((4==Width) && (Addr & 3)) ||
        ((2==Width) && (Addr & 1))) {
        CLIOutputString(" Unaligned Address\r\n");
        ErrorCode = ERROR_UNALIGNEDACCESS;
        goto ErrorReturn;
    }

    // get the value if it exists
    if ((i+1) < argc) {
        if (!strtohex(argv[i+1], (unsigned int *)&Value)) {
            ErrorCode = ERROR_BADARG;
            goto ErrorReturn;
        }    
    } else {
        ErrorCode = ERROR_MISSINGARGS;        
        goto ErrorReturn;    
    }

    // set the iteration count, or default to 1    
    if ((i+2) < argc) {
        if (!strtohex(argv[i+2], (unsigned int *)&Iterations)) {
            ErrorCode = ERROR_BADARG;
            goto ErrorReturn;
        }
    } else {
        Iterations = 1;
    }

    CLIOutputString("Write %x starting @ 0x%x for %u words\r\n", 
            Value,
            Addr,
            Iterations);
            
    for (i=0; i<Iterations; i+=Width) {
        switch (Width) {
        case 4:
            (*PULONG(Addr + i)) = Value;
			break;
        case 2:
            (*PUSHORT(Addr + i)) = (USHORT)Value;
			break;
        case 1:
            (*PUCHAR(Addr + i)) = (UCHAR)Value;
			break;
        }
    }
    
    CLIOutputString("\r\nOk");
    
    
ErrorReturn:
    return ErrorCode;	
}

int
MemTest(int argc, char *argv[])
{
	int32 ErrorCode = ERROR_SUCCESS;
	uint32 Saddr,Eaddr;
	uint32 Addr;
	
	if (argc < 2) {
        ErrorCode = ERROR_MISSINGARGS;        
        goto MemTestExit;        
    }
	if (!strtohex(argv[1], (unsigned int *)&Saddr)) {
        ErrorCode = ERROR_BADARG;
        goto MemTestExit;
    }
	if (!strtohex(argv[2], (unsigned int *)&Eaddr)) {
        ErrorCode = ERROR_BADARG;
        goto MemTestExit;
    }
	CLIOutputString("StartAddr:0x%x EndAddr:0x%x\r\n",Saddr,Eaddr);
    if(Saddr>Eaddr){
		ErrorCode = ERROR_BADARG;
        goto MemTestExit;
    }
	
	Addr = Saddr;
    do{
		(*PULONG(Addr)) = Addr;
		Addr+=4;
		
	}while(Addr<Eaddr);
	
	CLIOutputString("Check Data\r\n");
	
	Addr = Saddr;
	do{
		if(*((volatile uint32 *)(Addr))!=Addr){
			CLIOutputString("Memory:0x%x=0x%x\r\n",Addr,*((volatile unsigned char*)(Addr)));
		}
		Addr+=4;
	}while(Addr<Eaddr);
	
	CLIOutputString("Memory test complete\r\n");
MemTestExit:
	return ErrorCode;
}

